package com.education.platform.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.education.platform.entity.SmsCode;
import com.education.platform.exception.BusinessException;
import com.education.platform.mapper.SmsCodeMapper;
import com.education.platform.service.RedisService;
import com.education.platform.service.SmsService;
import com.education.platform.common.ResultCode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

/**
 * 短信服务实现类
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class SmsServiceImpl implements SmsService {

    private final SmsCodeMapper smsCodeMapper;
    private final RedisService redisService;

    private static final String SMS_LIMIT_KEY = "sms_limit:";
    private static final int SMS_LIMIT_COUNT = 5; // 每日限制发送次数
    private static final int SMS_INTERVAL = 60; // 发送间隔（秒）

    @Override
    public void sendCode(String mobile, String type) {
        // 检查发送频率限制
        String limitKey = SMS_LIMIT_KEY + mobile + ":" + type;
        Integer sendCount = redisService.get(limitKey);
        if (sendCount != null && sendCount >= SMS_LIMIT_COUNT) {
            throw new BusinessException(ResultCode.SMS_CODE_SEND_FAILED.getCode(), "今日发送次数已达上限");
        }

        // 检查发送间隔
        String intervalKey = "sms_interval:" + mobile;
        if (redisService.hasKey(intervalKey)) {
            throw new BusinessException(ResultCode.SMS_CODE_SEND_FAILED.getCode(), "发送过于频繁，请稍后再试");
        }

        // 生成验证码
        String code = RandomUtil.randomNumbers(6);
        
        // 保存到数据库
        SmsCode smsCode = new SmsCode();
        smsCode.setMobile(mobile);
        smsCode.setCode(code);
        smsCode.setType(type);
        smsCode.setUsed(false);
        smsCode.setExpireTime(LocalDateTime.now().plusMinutes(5)); // 5分钟过期
        smsCodeMapper.insert(smsCode);

        // 调用第三方短信服务发送（这里仅做模拟）
        boolean sendSuccess = sendSmsToProvider(mobile, code, type);
        
        if (sendSuccess) {
            // 增加发送次数计数
            redisService.increment(limitKey, 24 * 60 * 60); // 24小时过期
            
            // 设置发送间隔
            redisService.set(intervalKey, "1", SMS_INTERVAL);
            
            log.info("短信验证码发送成功：mobile={}, type={}, code={}", mobile, type, code);
        } else {
            throw new BusinessException(ResultCode.SMS_CODE_SEND_FAILED);
        }
    }

    @Override
    public boolean validateCode(String mobile, String code, String type) {
        SmsCode smsCode = smsCodeMapper.selectOne(
            new LambdaQueryWrapper<SmsCode>()
                .eq(SmsCode::getMobile, mobile)
                .eq(SmsCode::getCode, code)
                .eq(SmsCode::getType, type)
                .eq(SmsCode::getUsed, false)
                .gt(SmsCode::getExpireTime, LocalDateTime.now())
                .orderByDesc(SmsCode::getCreatedAt)
                .last("LIMIT 1")
        );

        if (smsCode != null) {
            // 标记验证码已使用
            smsCode.setUsed(true);
            smsCodeMapper.updateById(smsCode);
            return true;
        }
        
        return false;
    }

    /**
     * 调用第三方短信服务发送短信
     * 这里仅做模拟，实际项目中需要集成阿里云、腾讯云等短信服务
     */
    private boolean sendSmsToProvider(String mobile, String code, String type) {
        // 模拟发送成功
        log.info("模拟发送短信：mobile={}, code={}, type={}", mobile, code, type);
        return true;
    }
} 